//
// Created by Jisam on 2024/7/14.
//

#include <bits/stdc++.h>
using namespace std;

// 定义棋盘的大小
int n;
const int N = 505;
int a[N][N], vis[N][N];
// 定义移动方向
int dx[] = {-1, 1, 0, 0};
int dy[] = {0, 0, -1, 1};

/**
 * 深度优先搜索函数
 * @param x 当前位置的横坐标
 * @param y 当前位置的纵坐标
 * @param z 当前搜索的阈值
 */
void dfs(int x, int y, int z) {
    // 如果当前位置的值大于阈值或者已经被访问过，或者超出棋盘范围，则返回
    if (a[x][y] > z || vis[x][y] || vis[n][n]) return;
    vis[x][y] = 1;
    // 遍历四个方向
    for (int k = 0 ; k < 4; k ++) {
        int tx = x + dx[k];
        int ty = y + dy[k];
        // 如果移动后的位置超出棋盘范围或者已经被访问过，或者当前位置的值大于阈值，则跳过
        if (tx < 1 || tx > n || ty < 1 || ty > n || vis[tx][ty] || a[x][y] > z)
            continue;
        dfs(tx, ty, z);
    }
}

int main() {
    // 关闭同步标准输入输出，提高输入输出效率
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    // 输入棋盘的大小
    cin >> n;
    // 输入棋盘上的数值
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) cin >> a[i][j];
    }
    // 如果棋盘大小为1，直接输出棋盘上的值
    if (n == 1) {
        cout << a[1][1];
        return 0;
    }
    // 初始化最小值和搜索范围
    int l = 1, r = 1e9, md, ans = 1e9;
    // 使用二分查找确定最小的阈值
    while (l <= r) {
        md = (l + r) >> 1;
        // 初始化访问标记数组
        memset(vis, 0, sizeof(vis));
        // 从左上角开始深度优先搜索
        dfs(1, 1, md);
        // 如果右下角被访问到，更新最小值并缩小搜索范围
        if (vis[n][n]) {
            ans = min(ans, md);
            r = md - 1;
        } else {
            l = md + 1;
        }
    }
    // 输出最小的阈值
    cout << ans;
}
